#include<iostream>
#include<fstream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <sys/types.h>         
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/epoll.h>
#include<map>
//#include "sdata.h"

using namespace std;

void DataPack(char *buf_x,char *buf);
int CorDataSolve(int clientsockfd,char *buf);
int Quit_Back(int clientsockfd,char *buf);
int Fight_WatchDataSolve(int clientsockfd,int sumid,char *buf);
void Send_Qipan(int clientsockfd,int *pbuf,int flag);
int Game_DataSolve(int clientsockfd,int room_id);
int Guan_Zhan(int clientsockfd,int sumid,char *buf);
void Tell_Host_HeiQi(int clientsockfd);
void Tell_Gec_BaiQi(int clientsockfd);

int main(int argc, char const *argv[])
{
    //1.创建套接字
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd < 0)
    {
        perror("socket");
        return -1;
    }
    //2.绑定
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(atoi(argv[1]));
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    int ret =  bind(sockfd, (struct sockaddr*)(&addr),sizeof(addr));

    //3.设置监听模式 listen()
    listen(sockfd,5);

    struct sockaddr_in clientaddr;
    socklen_t len = sizeof(clientaddr);
    int clientsockfd = accept(sockfd,(struct sockaddr *)&clientaddr ,&len);
    printf("Client Ip Is %s\n",inet_ntoa(clientaddr.sin_addr));

    int id = 4;
    while(1) 
    {
        char buf[256] = {0}; 
        int ret = CorDataSolve(clientsockfd,buf);
        cout<<buf<<endl;
        cout<<"123"<<endl;
        if(ret < 0)
        {
            break;
        }
    }
    return 0;
}

/****************数据处理*****************/
int CorDataSolve(int clientsockfd,char *buf)
{
    //5.接收数据 recv()
    char buf_x[128] = {0}; 
    char *D_pack;//用于记录打包好数据的内存地址
    int ret = recv(clientsockfd, buf_x,128,0);//客户端关闭，返回0
    if(ret <1)//客户端掉线
    {
        cout<<"close(clientsockfd)"<<endl;
        close(clientsockfd);
        strcpy(buf,"diaoxian");
         return -1;
    }   
    //4.解析数据包，判断是否符合协议
    char head_x[32] = {0};     
    sscanf(buf_x,"{%[^:]:}",head_x);
    //解析出是坐标头协议
    if(!strcmp("cor",head_x))
    {
        DataPack(buf_x,buf);//返回的是客户端发来的坐标和输赢标志 格式：[x,y,flag=]
    } 
    else
    {
        cout<<"Error Format Data"<<endl;
        strcpy(buf,"Error");
        return -1;
    }
    return 0;
}

/*************退出、返回、悔棋数据收发协议*******************/
int Quit_Back(int clientsockfd,char *buf)
{  
    //5.接收数据 recv()
    char buf_x[128] = {0}; 
    char *D_pack;//用于记录打包好数据的内存地址
    int ret = recv(clientsockfd, buf_x,128,0);//客户端关闭，返回0
    if(ret <1)//客户端掉线
    {
        cout<<"close(clientsockfd)"<<endl;
        close(clientsockfd);
        strcpy(buf,"diaoxian");
        return -1;
    }   
    //4.解析数据包，判断是否符合协议
    char head_x[32] = {0};     
    sscanf(buf_x,"{%[^:]:}",head_x);
   
   //解析是投降协议
    if(!strcmp("success",head_x))
    {
        bzero(buf,strlen(buf));
        sscanf(buf_x,"{%s}",buf);
    }
    //解析是退出房间返回大厅协议
    else if(!strcmp("GuanTui",head_x) || !strcmp("Tui",head_x))
    {
        strcpy(buf,"tuichu");
        char abuf[] = "ok";
        write(clientsockfd,abuf,strlen(abuf));
    }
    //解析是悔棋协议
    else if(!strcmp("HuiQi",head_x))
    {
        strcpy(buf,"huiqi");
    }
    else
    {
        cout<<"Error Format Data"<<endl;
        strcpy(buf,"Error");
        return -1;
    }
    return 0;
}

/******************对战观战申请协议处理**********************/
int Fight_WatchDataSolve(int clientsockfd,int sumid,char *buf)
{
    //5.接收数据 recv()
    char buf_x[128] = {0}; 
    char *D_pack;//用于记录打包好数据的内存地址
    int ret = recv(clientsockfd, buf_x,128,0);//客户端关闭，返回0
    if(ret <1)//客户端掉线
    {
        cout<<"close(clientsockfd)"<<endl;
        close(clientsockfd);
        strcpy(buf,"diaoxian");
        return -1;
    }   
    //4.解析数据包，判断是否符合协议
    char head_x[32] = {0};     
    sscanf(buf_x,"{%[^:]:}",head_x);
    //解析是开始对战请求头协议
    if(!strcmp("gamereq",head_x))
    {
        strcpy(buf,"gamerequest");
    }
    //解析是观战请求头协议
    else if(!strcmp("guanzhan",head_x))
    {
        Guan_Zhan(clientsockfd,sumid,buf);
    }
    else
    {
        cout<<"Error Format Data"<<endl;
        strcpy(buf,"Error");
        return -1;
    }
    return 0;

}

/******************发送整个棋盘坐标信息给客户端****************/
void Send_Qipan(int clientsockfd,int *pbuf,int flag)
{
    char buf_s[32] = {0};
    int k = 0;
    char qipan[256] = {0};//用于棋盘和flag一起打包
    char temp[225] = {0};//将棋盘上的黑棋或白棋整型转换为字符型
    for (int i = 0; i < 15; i++) 
    {
        for (int j = 0; j < 15; j++)
        {
            temp[k] = pbuf[15*i+j] + '0';
            cout<<k<<endl;           
            ++k;
        }
        
    }
    //打包
    sprintf(qipan,"%s,flag=%d",temp,flag);
    //发送棋盘
    write(clientsockfd,qipan,strlen(qipan));
}

/***************打包数据******************/
void DataPack(char *buf_x,char *buf)
{
    int x,y,flag;
    sscanf(buf_x,"{cor:x=%d,y=%d,flag=%d}",&x,&y,&flag);
    sprintf(buf,"[%d,%d,flag=%d]",x,y,flag);  
}

/************告诉客场为白棋*******************/
void Tell_Gec_BaiQi(int clientsockfd)
{
    char buf[] = "{corlor_flag:2}";
    send(clientsockfd,buf,strlen(buf),0);
}

/************告诉主场为黑棋*******************/
void Tell_Host_HeiQi(int clientsockfd)
{
    char buf[] = "{corlor_flag:1}";
    send(clientsockfd,buf,strlen(buf),0);
}

/********************观战*****************/
int Guan_Zhan(int clientsockfd,int sumid,char *buf)
{
    //1.传入所有正在对战的房间号总数并发送给客户端
    send(clientsockfd,&sumid,4,0);
    //2.接收客户端发回的要观看的房间号
    if(sumid == 0)
    {
        strcpy(buf,"Noneid");
        return -1;
    }
    int id = 0;
    recv(clientsockfd,&id,4,0);
    //3.发送对应房间号棋盘数据回去给客户端

    if (id == 0)
    {
        //客户端还没进入,点击退出大厅
        strcpy(buf,"GuanTui");
    }
    else if(id > 0)
    {
        //提示观战,并返回房间id
        sprintf(buf,"GuanZhan:%d",&id);
    }
    return 0;
}

